#include "Program.h"
#include "Namespace.h"
#include "Class.h"
#include "ClassContent.h"

namespace FunctionViewer {
	Program::Program() {
		namespace_counter	= 0;
		first_namespace		= NULL;
		last_namespace		= NULL;
		current_namespace	= NULL;
		name				= "";
	}

	Program::~Program() {
		//Destory everything, without saving!
		while (first_namespace != NULL) DestoryNamespace(first_namespace);
	}

	void Program::Clear() {
		while (first_namespace != NULL) DestoryNamespace(first_namespace);
		namespace_counter = 0;
	}

	Namespace* Program::CreateNamespace(char* name) {
		Namespace* f_namespace;

		//allocate memory.
		f_namespace = (Namespace*)(malloc(sizeof(Namespace)));
		if (f_namespace == NULL) {
			printf("Memory allocation failed! Could not allocate memory for namespace!"); std::cout << std::endl;
			return NULL;
		}
#ifdef DEBUG_STRING
		std::cout << "WorksN1" << std::endl;
#endif

		f_namespace->Init(this, name);
#ifdef DEBUG_STRING
		std::cout << "WorksN2" << std::endl;
#endif

		return f_namespace;
	}

	bool Program::DestoryNamespace(Namespace* v_namespace) {
		v_namespace->DeInit();
		//Delete from memory
		free(v_namespace);
		//Everything is good, return true
		return true;
	}

	void Program::PrintProgramStructure() {
		/*
		DEBUG FUNCTION. FOR TESTING PURPOSES ONLY!!

		This function prints the program structure to the console window.

		Structure:
		+- Program
		  +- Namespace 1
			+- Class 1
			  +- ClassContent 1 (functions, variables, etc.)
			  +- ClassContent 2
		   +- Class 2
		+- Namespace 2
		  +- Class 3
		etc.
		*/
		char spatie = (char)32;
		char streep = (char)124;

		std::cout << "Program Structure:" << std::endl;
		std::printf("+- Program --> %s", name); std::cout << std::endl;
		for (Namespace *_namespace = first_namespace; _namespace!=NULL; _namespace = _namespace->next) {
			std::printf(" +- Namespace %lu --> %s", _namespace->id, _namespace->nname); std::cout << std::endl;
			for (Namespace *_namespacein = _namespace->first; _namespacein!=NULL; _namespacein = _namespacein->next) {
				std::printf(" %c  +- Namespace %lu --> %s", 
					(_namespace->next == NULL)? spatie : streep, _namespacein->id, _namespacein->nname); std::cout << std::endl;
				for (Class *_class = _namespacein->first_class; _class!=NULL; _class = _class->next) {
					std::printf(" %c  %c  +- Class %lu --> %s",
						(_namespace->next == NULL)? spatie : streep,
						(_namespacein->next == NULL)? spatie : streep, _class->id, _class->cname); std::cout << std::endl;
					for (ClassContent *_content = _class->first_content; _content!=NULL; _content = _content->next) {
						std::printf(" %c  %c  %c  +- Content %lu --> %s, %s, %s",
							(_namespace->next == NULL)? spatie : streep,
							(_namespacein->next == NULL)? spatie : streep,
							(_class->next == NULL)? spatie : streep, _content->id,
							_content->type, _content->funcname, _content->description); std::cout << std::endl;
					}
				}
			}
			for (Class *_class = _namespace->first_class; _class!=NULL; _class = _class->next) {
				std::printf(" %c  +- Class %lu --> %s",
					(_namespace->next == NULL)? spatie : streep, _class->id, _class->cname); std::cout << std::endl;
				for (ClassContent *_content = _class->first_content; _content!=NULL; _content = _content->next) {
					std::printf(" %c  %c  +- Content %lu --> %s, %s, %s",
						(_namespace->next == NULL)? spatie : streep,
						(_class->next == NULL)? spatie : streep, _content->id,
						_content->type, _content->funcname, _content->description); std::cout << std::endl;
				}
			}
		}
	}

	void Program::SetName(char* v_name) {
		name = v_name;
	}

	void Program::SaveFile(char* filename) {
		std::ofstream outFile;
		if (outFile.is_open()) {
			outFile << this->name << std::endl;
			for (Namespace *_namespace = first_namespace; _namespace!=NULL; _namespace=_namespace->next) {
				outFile << _namespace->nname << std::endl;
			}
		}
	}
}